using Gltf;
using Unity.Mathematics;

namespace Cesium3DTilesSelection
{
    public interface IPrepareRendererResources
    {
        /**
 * @brief Prepares renderer resources for the given tile.
 *
 * This method is invoked in the load thread, and it may not modify the tile.
 *
 * @param model The glTF model to prepare.
 * @param transform The tile's transformation.
 * @returns Arbitrary data representing the result of the load process. This
 * data is passed to {@link prepareInMainThread} as the `pLoadThreadResult`
 * parameter.
 */
        object prepareInLoadThread(Gltf.Model model, double4x4 transform);

        /**
         * @brief Further prepares renderer resources.
         *
         * This is called after {@link prepareInLoadThread}, and unlike that method,
         * this one is called from the same thread that called
         * {@link Tileset::updateView}.
         *
         * @param tile The tile to prepare.
         * @param pLoadThreadResult The value returned from
         * {@link prepareInLoadThread}.
         * @returns Arbitrary data representing the result of the load process.
         * Note that the value returned by {@link prepareInLoadThread} will _not_ be
         * automatically preserved and passed to {@link free}. If you need to free
         * that value, do it in this method before returning. If you need that value
         * later, add it to the object returned from this method.
         */
        object prepareInMainThread(Tile tile, object pLoadThreadResult);

        /**
           * @brief Prepares a raster overlay tile.
           *
           * This method is invoked in the load thread, and it may not modify the tile.
           *
           * @param image The raster tile image to prepare.
           * @returns Arbitrary data representing the result of the load process. This
           * data is passed to {@link prepareRasterInMainThread} as the
           * `pLoadThreadResult` parameter.
           */
        object prepareRasterInLoadThread(ImageCesium image);

        /**
         * @brief Further preprares a raster overlay tile.
         *
         * This is called after {@link prepareRasterInLoadThread}, and unlike that
         * method, this one is called from the same thread that called
         * {@link Tileset::updateView}.
         *
         * @param rasterTile The raster tile to prepare.
         * @param pLoadThreadResult The value returned from
         * {@link prepareInLoadThread}.
         * @returns Arbitrary data representing the result of the load process. Note
         * that the value returned by {@link prepareRasterInLoadThread} will _not_ be
         * automatically preserved and passed to {@link free}. If you need to free
         * that value, do it in this method before returning. If you need that value
         * later, add it to the object returned from this method.
         */
        object prepareRasterInMainThread(RasterOverlayTile rasterTile, object pLoadThreadResult);

        /**
         * @brief Frees previously-prepared renderer resources for a raster tile.
         *
         * This method is always called from the thread that called
         * {@link Tileset::updateView} or deleted the tileset.
         *
         * @param rasterTile The tile for which to free renderer resources.
         * @param pLoadThreadResult The result returned by
         * {@link prepareRasterInLoadThread}. If {@link prepareRasterInMainThread}
         * has already been called, this parameter will be `nullptr`.
         * @param pMainThreadResult The result returned by
         * {@link prepareRasterInMainThread}. If {@link prepareRasterInMainThread}
         * has not yet been called, this parameter will be `nullptr`.
         */
        void freeRaster(RasterOverlayTile rasterTile, object pLoadThreadResult, object pMainThreadResult);

        /**
         * @brief Attaches a raster overlay tile to a geometry tile.
         *
         * @param tile The geometry tile.
         * @param overlayTextureCoordinateID The ID of the overlay texture coordinate
         * set to use.
         * @param rasterTile The raster overlay tile to add. The raster tile will have
         * been previously prepared with a call to {@link prepareRasterInLoadThread}
         * followed by {@link prepareRasterInMainThread}.
         * @param pMainThreadRendererResources The renderer resources for this raster
         * tile, as created and returned by {@link prepareRasterInMainThread}.
         * @param translation The translation to apply to the texture coordinates
         * identified by `overlayTextureCoordinateID`. The texture coordinates to use
         * to sample the raster image are computed as `overlayTextureCoordinates *
         * scale + translation`.
         * @param scale The scale to apply to the texture coordinates identified by
         * `overlayTextureCoordinateID`. The texture coordinates to use to sample the
         * raster image are computed as `overlayTextureCoordinates * scale +
         * translation`.
         */

        void attachRasterInMainThread(Tile tile, int overlayTextureCoordinateID,
        RasterOverlayTile rasterTile, object pMainThreadRendererResources,
        double2 translation, double2 scale);
        void detachRasterInMainThread(Tile tile, int textureCoordinateID, RasterOverlayTile pReadyTile, object pRendererResources);

        void free(Tile tile, object pLoadThreadResult, object pMainThreadResult);
    }
}